﻿/* 
 * 收支类型 True 为收入、False 为支出
 * 所有账务记录金额的修改在此处操作，方便统计
 * Entry 记录更改后必须更新钱袋
 * EntryGroup 更改后必须更新 mGroup 列表
 */ 

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Diagnostics;
using System.Xml;
using System.Reflection;
using System.IO;
using System.IO.Compression;
using System.Windows.Forms;
using System.Drawing;

using FCNS;
using FCNS.KeepMoney.Configuration;
using FCNS.KeepMoney.UI;
using FCNS.KeepMoney.Util;

namespace FCNS.KeepMoney.Data
{
    public sealed class KMData : DataSet
    {
        private void InitializeComponent()
        {
            ((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
            // 
            // KMData
            // 
            this.DataSetName = "KeepMoney";
            ((System.ComponentModel.ISupportInitialize)(this)).EndInit();

        }

        public static bool IsDataLoadSuccessfully
        {
            get { return dtEntry != null; }
        }

        public KMData(string file, bool newFile)
        {
            if (newFile)
                Init();
            else
            {
                try
                {
                    FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
                    GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Decompress);
                    StreamReader reader = new StreamReader(compressionStream);
                    this.ReadXml(reader);
                    reader.Dispose();
                }
                catch
                { this.ReadXml(file); }
                finally
                {
                    try
                    {
                        InitData id = new InitData();
                        id.UpdateDataSet(this);
                    }
                    catch
                    {
                        MessageBox.Show("无法打开 " + file + "\r\n" + "文件丢失或文件路径无法访问");
                    }
                    //foreach (DataRow row in this.Tables["Groups"].Rows)
                    //    if (!(bool)row["IorE"])
                    //        foreach (DataRow r in this.Tables["Entrys"].Rows)
                    //            MessageBox.Show(r["Money"].ToString());
                }
            }

            dtEntryGroup = this.Tables["Groups"];
            Debug.Assert(dtEntryGroup != null, "Groups");
            dtEntry = this.Tables["Entrys"];
            Debug.Assert(dtEntry != null, "Entrys");
            dtEntryTag = this.Tables["Tags"];
            Debug.Assert(dtEntryTag != null, "Tags");
            dtEntryBank = this.Tables["Banks"];
            Debug.Assert(dtEntryBank != null, "Banks");
            dtAccount = this.Tables["Accounts"];
            Debug.Assert(dtAccount != null, "Accounts");
            dtGtdGroup = this.Tables["GtdGroups"];
            Debug.Assert(dtGtdGroup != null, "GtdGroups");
            dtGtdEntry = this.Tables["GtdEntrys"];
            Debug.Assert(dtGtdEntry != null, "GtdEntrys");
            dtRegularEntry = this.Tables["RegularEntrys"];
            Debug.Assert(dtRegularEntry != null, "RegularEntrys");
            dtInterest = this.Tables["Interests"];
            Debug.Assert(dtInterest != null, "Interests");
        }

        private void Init()
        {
            this.Reset();
            this.DataSetName = "KeepMoney";
            InitData id = new InitData();
            id.InitDataSet(this);
        }

        #region 属性
        static DataTable dtInterest = null;
        public static DataTable DataTableInterest
        {
            get
            {
                //预防第三方开发清空此表导致异常
                if (dtInterest.Rows.Count == 0)
                {
                    InitData init = new InitData();
                    init.InitInterestsData(dtInterest);
                }

                return dtInterest;
            }
        }

        static DataTable dtRegularEntry = null;
        public static DataTable DataTableRegular
        {
            get { return dtRegularEntry; }
        }

        static DataTable dtEntryGroup = null;
        public static DataTable DataTableGroups
        {
            get
            {
                if (dtEntryGroup.Rows.Count == 0)
                {
                    InitData init = new InitData();
                    init.InitGroupsData(dtEntryGroup);
                }
                return dtEntryGroup;
            }
        }

        static DataTable dtEntry = null;
        public static DataTable DataTableEntrys
        {
            get { return dtEntry; }
        }

        static DataTable dtEntryTag = null;
        public static DataTable DataTableTags
        {
            get { return dtEntryTag; }
        }

        static DataTable dtEntryBank = null;
        public static DataTable DataTableBanks
        {
            get
            {
                if (dtEntryBank.Rows.Count == 0)
                {
                    InitData init = new InitData();
                    init.InitBanksData(dtEntryBank);
                }
                return dtEntryBank;
            }
        }

        static DataTable dtAccount = null;
        public static DataTable DataTableAccounts
        {
            get { return dtAccount; }
        }

        static DataTable dtGtdGroup = null;
        public static DataTable DataTableGtdGroups
        {
            get
            {
                if (dtGtdGroup.Rows.Count == 0)
                {
                    InitData init = new InitData();
                    init.InitGtdGroupData(dtGtdGroup);
                }
                return dtGtdGroup;
            }
        }

        static DataTable dtGtdEntry = null;
        public static DataTable DataTableGtdEntrys
        {
            get { return dtGtdEntry; }
        }
        #endregion

        public static DataRow[] GetAllSubGroupRows(int parentGroupId)
        {
            List<DataRow> rows = new List<DataRow>();
            DataRow[] r = dtEntryGroup.Select("ParentGroupId = " + parentGroupId);
            rows.AddRange(r);
            foreach (DataRow row in r)
                rows.AddRange(GetAllSubGroupRows((int)row["Id"]));

            return rows.ToArray();
        }

        public static string GetGroupNameById(int groupId)
        {
            DataRow[] rows = dtEntryGroup.Select("Id = " + groupId);
            if (rows.Length == 0)
                return string.Empty;
            else
                return (string)rows[0]["Name"];
        }

        public static DataRow[] GetEntrysByDate(DateTime start, DateTime end)
        {
            StringBuilder sb = new StringBuilder("Date >= '" + DateTime.ParseExact(start.ToString("yyyyMMdd"), "yyyyMMdd", null) +
                " ' and Date <= '" + DateTime.ParseExact(end.ToString("yyyyMMdd"), "yyyyMMdd", null) +
                    " '");

            return dtEntry.Select(sb.ToString());
        }

        public static bool SetRowValue(DataTableName tableName, int rowId, string columnName, object newValue)
        {
            bool b = true;
            try
            {
                switch (tableName)
                {
                    case DataTableName.Banks:
                        dtEntryBank.Select("Id = " + rowId)[0][columnName] = newValue;
                        break;

                    default:
                        b = false;
                        break;
                }
            }
            catch { b = false; }
            return b;
        }
    }


    internal class InitData
    {
        internal void InitDataSet(DataSet ds)
        {
            #region Interests
            DataTable dtI = new DataTable("Interests");
            DataColumn I1 = new DataColumn("Id", typeof(int));
            I1.AllowDBNull = false;
            I1.Unique = true;
            I1.AutoIncrement = true;
            I1.AutoIncrementSeed = 0;
            I1.AutoIncrementStep = 1;
            I1.ReadOnly = true;

            DataColumn I2 = new DataColumn("Name", typeof(string));
            I2.AllowDBNull = false;
            I2.Unique = false;
            I2.DefaultValue = string.Empty;

            DataColumn I3 = new DataColumn("Mode", typeof(int));
            I3.AllowDBNull = false;
            I3.DefaultValue = 0;
            I3.Unique = false;

            DataColumn I4 = new DataColumn("Value", typeof(decimal));
            I4.AllowDBNull = false;
            I4.DefaultValue = 0;
            I4.Unique = false;


            dtI.Columns.AddRange(new DataColumn[] { I1, I2, I3, I4 });

            InitInterestsData(dtI);
            #endregion

            #region groups //回收站id=0 最高
            DataTable dtG = new DataTable("Groups");
            DataColumn g1 = new DataColumn("Id", typeof(int));
            g1.AllowDBNull = false;
            g1.Unique = true;
            g1.AutoIncrement = true;
            g1.AutoIncrementSeed = 1;
            g1.AutoIncrementStep = 1;
            g1.ReadOnly = true;

            DataColumn g2 = new DataColumn("Name", typeof(string));
            g2.AllowDBNull = false;
            g2.Unique = false;
            g2.DefaultValue = string.Empty;

            DataColumn g3 = new DataColumn("IorE", typeof(bool));
            g3.AllowDBNull = false;
            g3.Unique = false;
            g3.DefaultValue = true;

            DataColumn g4 = new DataColumn("ParentGroupId", typeof(int));
            g4.AllowDBNull = false;
            g4.Unique = false;
            g4.DefaultValue = 0;

            DataColumn g5 = new DataColumn("IconIndex", typeof(int));
            g5.AllowDBNull = false;
            g5.Unique = false;
            g5.DefaultValue = 0;

            DataColumn g6 = new DataColumn("Note", typeof(string));
            g6.AllowDBNull = false;
            g6.Unique = false;
            g6.DefaultValue = string.Empty;

            DataColumn g7 = new DataColumn("Dirty", typeof(bool));
            g7.AllowDBNull = false;
            g7.DefaultValue = false;
            g7.Unique = false;

            dtG.Columns.AddRange(new DataColumn[] { g1, g2, g3, g4, g5, g6, g7 });

            InitGroupsData(dtG);
            #endregion

            #region entrys
            DataTable dtE = new DataTable("Entrys");

            DataColumn e1 = new DataColumn("Id", typeof(int));
            e1.AllowDBNull = false;
            e1.AutoIncrementStep = 1;
            e1.AutoIncrementSeed = 1;
            e1.AutoIncrement = true;
            e1.Unique = true;
            e1.ReadOnly = true;

            DataColumn e2 = new DataColumn("GroupId", typeof(int));
            e2.AllowDBNull = false;
            e2.Unique = false;

            DataColumn e3 = new DataColumn("Tag", typeof(string));
            e3.AllowDBNull = true;
            e3.Unique = false;

            DataColumn e4 = new DataColumn("Name", typeof(string));
            e4.AllowDBNull = false;
            e4.DefaultValue = string.Empty;
            e4.Unique = false;

            DataColumn e5 = new DataColumn("Money", typeof(decimal));
            e5.AllowDBNull = false;
            e5.Unique = false;
            e5.DefaultValue = 0;

            DataColumn e6 = new DataColumn("Date", typeof(DateTime));
            e6.AllowDBNull = false;
            e6.Unique = false;

            DataColumn e7 = new DataColumn("Note", typeof(string));
            e7.AllowDBNull = false;
            e7.DefaultValue = string.Empty;
            e7.Unique = false;

            DataColumn e8 = new DataColumn("BankId", typeof(int));
            e8.AllowDBNull = false;
            e8.Unique = false;

            DataColumn e9 = new DataColumn("AlertDate", typeof(DateTime));
            e9.AllowDBNull = true;
            e9.Unique = false;

            DataColumn e10 = new DataColumn("EntryType", typeof(int));
            e10.Unique = false;
            e10.AllowDBNull = false;
            e10.DefaultValue = (int)KMDEntryType.Normal;

            DataColumn e11 = new DataColumn("Mark", typeof(string));
            e11.DefaultValue = string.Empty;
            e11.Unique = false;
            e11.AllowDBNull = true;

            dtE.Columns.AddRange(new DataColumn[] { e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 });

            #endregion

            #region tags
            DataTable dtT = new DataTable("Tags");

            DataColumn t2 = new DataColumn("Name", typeof(string));
            t2.AllowDBNull = false;
            t2.Unique = true;
            t2.DefaultValue = string.Empty;

            DataColumn t3 = new DataColumn("Amout", typeof(int));
            t3.AllowDBNull = false;
            t3.Unique = false;
            t3.DefaultValue = 0;

            dtT.Columns.Add(t2);
            dtT.Columns.Add(t3);

            InitTagData(dtT);
            #endregion

            #region Banks
            DataTable dtB = new DataTable("Banks");
            DataColumn b1 = new DataColumn("Id", typeof(int));
            b1.AllowDBNull = false;
            b1.Unique = true;
            b1.AutoIncrement = true;
            b1.AutoIncrementSeed = 1;
            b1.AutoIncrementStep = 1;
            b1.ReadOnly = true;

            DataColumn b2 = new DataColumn("Name", typeof(string));
            b2.AllowDBNull = true;
            b2.Unique = false;
            b2.DefaultValue = string.Empty;

            DataColumn b3 = new DataColumn("Url", typeof(string));
            b3.AllowDBNull = false;
            b3.DefaultValue = string.Empty;
            b3.Unique = false;

            DataColumn b4 = new DataColumn("Credit", typeof(decimal));
            b4.AllowDBNull = false;
            b4.DefaultValue = 0;
            b4.Unique = false;

            DataColumn b5 = new DataColumn("Default", typeof(bool));
            b5.AllowDBNull = false;
            b5.DefaultValue = false;
            b5.Unique = false;

            DataColumn b6 = new DataColumn("Balance", typeof(decimal));
            b6.AllowDBNull = false;
            b6.DefaultValue = 0;
            b6.Unique = false;

            DataColumn b7 = new DataColumn("Visible", typeof(bool));
            b7.Unique = false;
            b7.AllowDBNull = false;
            b7.DefaultValue = true;

            DataColumn b8 = new DataColumn("Enable", typeof(bool));
            b8.Unique = false;
            b8.AllowDBNull = false;
            b8.DefaultValue = true;

            dtB.Columns.AddRange(new DataColumn[] { b1, b2, b3, b4, b5, b6, b7, b8 });

            InitBanksData(dtB);
            #endregion

            #region Accounts
            DataTable dtA = new DataTable("Accounts");
            DataColumn a1 = new DataColumn("Id", typeof(int));
            a1.AllowDBNull = false;
            a1.Unique = true;
            a1.AutoIncrement = true;
            a1.AutoIncrementSeed = 1;
            a1.AutoIncrementStep = 1;
            a1.ReadOnly = true;

            DataColumn a2 = new DataColumn("Name", typeof(string));
            a2.AllowDBNull = false;
            a2.Unique = true;
            a2.DefaultValue = string.Empty;

            DataColumn a3 = new DataColumn("Password", typeof(string));
            a3.AllowDBNull = false;
            a3.Unique = false;

            DataColumn a4 = new DataColumn("Tag", typeof(string));
            a4.AllowDBNull = false;
            a4.Unique = true;
            a4.DefaultValue = string.Empty;

            dtA.Columns.AddRange(new DataColumn[] { a1, a2, a3, a4 });

            DataRow ar = dtA.NewRow();
            ar["Name"] = "admin";
            ar["Password"] = "admin";
            ar["Tag"] = "kmoney";
            dtA.Rows.Add(ar);
            #endregion

            #region GtdGroups
            DataTable dtgg = new DataTable("GtdGroups");

            DataColumn gg1 = new DataColumn("Id", typeof(int));
            gg1.Unique = true;
            gg1.AutoIncrement = true;
            gg1.AutoIncrementSeed = 0;
            gg1.AutoIncrementStep = 1;
            gg1.AllowDBNull = false;
            gg1.ReadOnly = true;

            DataColumn gg2 = new DataColumn("Name", typeof(string));
            gg2.Unique = false;
            gg2.AllowDBNull = false;
            gg2.DefaultValue = string.Empty;

            DataColumn gg3 = new DataColumn("Color", typeof(int));
            gg3.AllowDBNull = false;
            gg3.Unique = false;

            DataColumn gg4 = new DataColumn("Checked", typeof(bool));
            gg4.Unique = false;
            gg4.AllowDBNull = false;
            gg4.DefaultValue = true;

            dtgg.Columns.AddRange(new DataColumn[] { gg1, gg2, gg3, gg4 });

            InitGtdGroupData(dtgg);
            #endregion

            #region GtdEntrys
            DataTable dtge = new DataTable("GtdEntrys");

            DataColumn ge1 = new DataColumn("Id", typeof(int));
            ge1.Unique = true;
            ge1.AutoIncrementStep = 1;
            ge1.AutoIncrementSeed = 0;
            ge1.AutoIncrement = true;
            ge1.AllowDBNull = false;

            DataColumn ge2 = new DataColumn("GtdGroupId", typeof(int));
            ge2.AllowDBNull = false;
            ge2.Unique = false;
            ge2.DefaultValue = 0;

            DataColumn ge3 = new DataColumn("Name", typeof(string));
            ge3.AllowDBNull = false;
            ge3.Unique = false;
            ge3.DefaultValue = string.Empty;

            DataColumn ge4 = new DataColumn("Note", typeof(string));
            ge4.Unique = false;
            ge4.AllowDBNull = false;
            ge4.DefaultValue = string.Empty;

            DataColumn ge5 = new DataColumn("StartDateTime", typeof(DateTime));
            ge5.AllowDBNull = false;
            ge5.Unique = false;

            DataColumn ge6 = new DataColumn("EndDateTime", typeof(DateTime));
            ge6.AllowDBNull = false;
            ge6.Unique = false;

            DataColumn ge7 = new DataColumn("Finish", typeof(bool));
            ge7.AllowDBNull = false;
            ge7.Unique = false;
            ge7.DefaultValue = false;

            DataColumn ge8 = new DataColumn("Alert", typeof(string));
            ge8.AllowDBNull = true;
            ge8.Unique = false;

            DataColumn ge9 = new DataColumn("AlertType", typeof(string));
            ge9.AllowDBNull = true;
            ge9.Unique = false;

            DataColumn ge10 = new DataColumn("Level", typeof(int));
            ge10.AllowDBNull = false;
            ge10.Unique = false;
            ge10.DefaultValue = 0;

            dtge.Columns.AddRange(new DataColumn[] { ge1, ge2, ge3, ge4, ge5, ge6, ge7, ge8, ge9, ge10 });
            #endregion

            #region RegularEntrys
            DataTable dtre = new DataTable("RegularEntrys");

            DataColumn re1 = new DataColumn("Id", typeof(int));
            re1.Unique = true;
            re1.AutoIncrement = true;
            re1.AutoIncrementSeed = 0;
            re1.AutoIncrementStep = 1;
            re1.AllowDBNull = false;

            DataColumn re2 = new DataColumn("Name", typeof(string));
            re2.Unique = false;
            re2.AllowDBNull = false;
            re2.DefaultValue = "新增账务";

            DataColumn re3 = new DataColumn("Money", typeof(decimal));
            re3.AllowDBNull = false;
            re3.Unique = false;
            re3.DefaultValue = 0;

            DataColumn re4 = new DataColumn("Day", typeof(int));//账单日
            re4.Unique = false;
            re4.AllowDBNull = false;
            re4.DefaultValue = 24;

            DataColumn re5 = new DataColumn("Time", typeof(int));//期数
            re5.Unique = false;
            re5.AllowDBNull = false;
            re5.DefaultValue = 12;

            DataColumn re6 = new DataColumn("StartDate", typeof(DateTime));
            re6.Unique = false;
            re6.AllowDBNull = false;

            DataColumn re7 = new DataColumn("Finish", typeof(int));
            re7.Unique = false;
            re7.AllowDBNull = false;
            re7.DefaultValue = 0;

            DataColumn re8 = new DataColumn("GroupId", typeof(int));
            re8.Unique = false;
            re8.AllowDBNull = false;
            re8.DefaultValue = 0;

            DataColumn re10 = new DataColumn("BankId", typeof(int));
            re10.AllowDBNull = false;
            re10.Unique = false;
            re10.DefaultValue = 0;

            DataColumn re9 = new DataColumn("Note", typeof(string));
            re9.Unique = false;
            re9.AllowDBNull = false;
            re9.DefaultValue = string.Empty;

            DataColumn re11 = new DataColumn("InterestId", typeof(int));
            re11.Unique = false;
            re11.AllowDBNull = false;
            re11.DefaultValue = 0;

            DataColumn re12 = new DataColumn("UseCredit", typeof(bool));
            re12.Unique = false;
            re12.AllowDBNull = false;
            re12.DefaultValue = false;

            DataColumn re13 = new DataColumn("Compound", typeof(bool));
            re13.AllowDBNull = false;
            re13.DefaultValue = false;
            re13.Unique = false;


            dtre.Columns.AddRange(new DataColumn[] { re1, re2, re3, re4, re5, 
                re6, re7, re8, re9, re10,re11,re12,re13 });

            ds.Tables.Add(dtre);
            #endregion

            ds.Tables.AddRange(new DataTable[] { dtG, dtE, dtT, dtB, dtA, dtgg, dtge, dtI });
        }


        internal void InitTagData(DataTable table)
        {
            DataRow row1 = table.NewRow();
            row1["Name"] = LanguageUtil.借款;
            table.Rows.Add(row1);

            DataRow row2 = table.NewRow();
            row2["Name"] = LanguageUtil.贷款;
            table.Rows.Add(row2);
        }

        internal void InitGtdGroupData(DataTable table)
        {
            DataRow row = table.NewRow();
            row["Name"] = "工作";
            row["Color"] = 0;
            row["Checked"] = true;
            table.Rows.Add(row);
        }

        internal void InitInterestsData(DataTable table)
        {
            DataRow d1 = table.NewRow();
            d1["Name"] = "信用卡";
            d1["Mode"] = 0;
            d1["Value"] = 0.0005;

            DataRow d2 = table.NewRow();
            d2["Name"] = "0.05%";
            d2["Value"] = 0.0005;

            table.Rows.Add(d1);
            table.Rows.Add(d2);
        }

        internal void InitBanksData(DataTable table)
        {
            DataRow br1 = table.NewRow();
            br1["Name"] = "钱包";
            br1["Url"] = "http://www.keepmoney.org";
            br1["Default"] = true;
            table.Rows.Add(br1);
        }

        internal void InitGroupsData(DataTable table)
        {
            DataRow gr2 = table.NewRow();
            gr2["Name"] = "收入";
            gr2["IorE"] = true;
            gr2["ParentGroupId"] = 0;
            gr2["IconIndex"] = 1;
            gr2["Dirty"] = false;

            DataRow gr3 = table.NewRow();
            gr3["Name"] = "支出";
            gr3["IorE"] = false;
            gr3["ParentGroupId"] = 0;
            gr3["IconIndex"] = 2;
            gr3["Dirty"] = false;

            table.Rows.Add(gr2);
            table.Rows.Add(gr3);
        }


        internal void UpdateDataSet(DataSet ds)
        {
            #region 4.0 => 4.1
            if (!ds.Tables.Contains("Interests"))
            {
                DataTable dtI = new DataTable("Interests");
                DataColumn I1 = new DataColumn("Id", typeof(int));
                I1.AllowDBNull = false;
                I1.Unique = true;
                I1.AutoIncrement = true;
                I1.AutoIncrementSeed = 0;
                I1.AutoIncrementStep = 1;
                I1.ReadOnly = true;

                DataColumn I2 = new DataColumn("Name", typeof(string));
                I2.AllowDBNull = false;
                I2.Unique = false;
                I2.DefaultValue = string.Empty;

                DataColumn I3 = new DataColumn("Mode", typeof(int));
                I3.AllowDBNull = false;
                I3.DefaultValue = 0;
                I3.Unique = false;

                DataColumn I4 = new DataColumn("Value", typeof(decimal));
                I4.AllowDBNull = false;
                I4.DefaultValue = 0;
                I4.Unique = false;

                dtI.Columns.AddRange(new DataColumn[] { I1, I2, I3, I4 });
                ds.Tables.Add(dtI);
                InitInterestsData(dtI);


                DataColumn re11 = new DataColumn("InterestId", typeof(int));
                re11.Unique = false;
                re11.AllowDBNull = false;
                re11.DefaultValue = 0;
                ds.Tables["RegularEntrys"].Columns.Add(re11);
            }
            #endregion

            #region 4.1 => 4.2
            if (!ds.Tables["RegularEntrys"].Columns.Contains("UseCredit"))
            {
                DataColumn re12 = new DataColumn("UseCredit", typeof(bool));
                re12.Unique = false;
                re12.AllowDBNull = false;
                re12.DefaultValue = false;

                DataColumn re13 = new DataColumn("Compound", typeof(bool));
                re13.AllowDBNull = false;
                re13.DefaultValue = false;
                re13.Unique = false;

                ds.Tables["RegularEntrys"].Columns.Add(re12);
                ds.Tables["RegularEntrys"].Columns.Add(re13);


                ds.Tables["GtdGroups"].Columns["Id"].ReadOnly = true;


                InitTagData(ds.Tables["Tags"]);

            }

            foreach (DataRow row in ds.Tables["Groups"].Rows)
                if (!(bool)row["IorE"])
                    foreach (DataRow r in ds.Tables["Entrys"].Rows)
                        if ((int)r["GroupId"] == (int)row["Id"] && (decimal)r["Money"]>0)
                            r["Money"] = -(decimal)r["Money"];
            #endregion

        }
    }
}